﻿using System;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
using Caliburn.Micro;
using YiJing.Model;

namespace YiJing.ViewModels
{
    [Export(typeof(HexagramViewModel)), PartCreationPolicy(CreationPolicy.NonShared)]
    public class HexagramViewModel : PropertyChangedBase
    {
        private readonly TrigramViewModel[] _trigrams = new TrigramViewModel[4];
        private HexagramFigure _hexagram;

        private object _selectedTrigram;
        private bool _showTrigramDetails;

        public event EventHandler OnFigureChanged;

        public HexagramViewModel()
        {
            var trigramNames = new[] {"Above", "Upper", "Lower", "Below"};

            for (var i = 0; i < trigramNames.Length; ++i)
            {
                _trigrams[i] = new TrigramViewModel
                               {
                                   Position = i,
                                   Header = trigramNames[i].ToLower(),
                                   Figure = TrigramFigure.FromValue(i)
                               };
            }

            HexagramNumber = 1;
            SelectedTrigram = _trigrams.Last();
        }

        public bool ShowTrigramDetails
        {
            get { return _showTrigramDetails; }
            set
            {
                if (value == ShowTrigramDetails) return;

                _showTrigramDetails = value;
                NotifyOfPropertyChange(() => ShowTrigramDetails);
            }
        }

        public int HexagramNumber
        {
            get { return _hexagram != null ? _hexagram.Value : 0; }
            set
            {
                if (value != HexagramNumber) 
                    Figure = HexagramFigure.FromValue(value);
            }
        }

        public HexagramFigure Figure
        {
            get { return _hexagram; }
            set
            {
                if (value == Figure) return;

                SubscribeEvents(false);
                _hexagram = value;
                SubscribeEvents(true);

                NotifyOfHexagramChange();
            }
        }

        public object Trigrams
        {
            get { return _trigrams; }
        }

        public object SelectedTrigram
        {
            get { return _selectedTrigram; }
            set
            {
                if (value == SelectedTrigram) return;
                _selectedTrigram = value;
                NotifyOfPropertyChange(() => SelectedTrigram);
            }
        }

        private void OnLineChanged(object sender, PropertyChangedEventArgs e)
        {
            NotifyOfHexagramChange();
        }

        private void UpdateTrigrams()
        {
            var trigrams = _hexagram.Trigrams.ToArray();

            for (var i = 0; i < _trigrams.Length; ++i)
                _trigrams[i].Figure = trigrams[i];

            NotifyOfPropertyChange(() => SelectedTrigram);
        }

        private void SubscribeEvents(bool subscribe)
        {
            if (_hexagram == null) return;

            if (subscribe)
            {
                foreach (var line in _hexagram.Lines)
                    line.PropertyChanged += OnLineChanged;
            }
            else
            {
                foreach (var line in _hexagram.Lines)
                    line.PropertyChanged -= OnLineChanged;
            }
        }

        private void NotifyOfHexagramChange()
        {
            UpdateTrigrams();

            NotifyOfPropertyChange(() => Figure);
            NotifyOfPropertyChange(() => HexagramNumber);

            if (OnFigureChanged != null) OnFigureChanged(this, EventArgs.Empty);
        }
    }
}
